package com.xp.controller;

import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.xp.dto.flow.FlowExecutionDTO;
import com.xp.dto.flow.FlowExecutionRequest;
import com.xp.dto.flow.FlowQueryRequest;
import com.xp.service.FlowExecutionService;
import com.xp.utils.Result;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.tags.Tag;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;

import jakarta.validation.Valid;
import jakarta.validation.constraints.NotBlank;
import jakarta.validation.constraints.NotNull;
import java.time.LocalDateTime;
import java.util.List;
import java.util.Map;

/**
 * 流程执行管理控制器
 * 
 * @author xp
 * @since 2025-01-01
 */
@Slf4j
@RestController
@RequestMapping("/flow-executions")
@RequiredArgsConstructor
@Validated
@Tag(name = "流程执行管理", description = "流程执行、监控、统计分析等接口")
public class FlowExecutionController {

    private final FlowExecutionService flowExecutionService;

    /**
     * 分页查询流程执行记录
     */
    @GetMapping("/page")
    @Operation(summary = "分页查询流程执行记录", description = "支持多条件筛选的流程执行记录分页查询")
    public Result<IPage<FlowExecutionDTO>> getFlowExecutionPage(
            @Parameter(description = "页码", required = true) @RequestParam(defaultValue = "1") Integer current,
            @Parameter(description = "每页大小", required = true) @RequestParam(defaultValue = "10") Integer size,
            @Parameter(description = "流程编码") @RequestParam(required = false) String flowCode,
            @Parameter(description = "流程名称") @RequestParam(required = false) String flowName,
            @Parameter(description = "执行状态列表") @RequestParam(required = false) List<Integer> statusList,
            @Parameter(description = "链路追踪ID") @RequestParam(required = false) String traceId,
            @Parameter(description = "应用名称") @RequestParam(required = false) String applicationName,
            @Parameter(description = "执行者ID") @RequestParam(required = false) Long executorId,
            @Parameter(description = "开始时间起") @RequestParam(required = false) String startTimeStart,
            @Parameter(description = "开始时间止") @RequestParam(required = false) String startTimeEnd,
            @Parameter(description = "结束时间起") @RequestParam(required = false) String endTimeStart,
            @Parameter(description = "结束时间止") @RequestParam(required = false) String endTimeEnd,
            @Parameter(description = "排序字段") @RequestParam(required = false) String sortField,
            @Parameter(description = "排序方式") @RequestParam(required = false) String sortOrder) {
        
        Page<FlowExecutionDTO> page = new Page<>(current, size);
        
        FlowQueryRequest queryRequest = new FlowQueryRequest();
        queryRequest.setFlowCode(flowCode);
        queryRequest.setFlowName(flowName);
        queryRequest.setStatusList(statusList);
        queryRequest.setTraceId(traceId);
        queryRequest.setApplicationName(applicationName);
        queryRequest.setExecutorId(executorId);
        // 转换时间字符串为LocalDateTime
        if (startTimeStart != null && !startTimeStart.isEmpty()) {
            queryRequest.setStartTimeBegin(LocalDateTime.parse(startTimeStart));
        }
        if (startTimeEnd != null && !startTimeEnd.isEmpty()) {
            queryRequest.setStartTimeEnd(LocalDateTime.parse(startTimeEnd));
        }
        if (endTimeStart != null && !endTimeStart.isEmpty()) {
            queryRequest.setEndTimeBegin(LocalDateTime.parse(endTimeStart));
        }
        if (endTimeEnd != null && !endTimeEnd.isEmpty()) {
            queryRequest.setEndTimeEnd(LocalDateTime.parse(endTimeEnd));
        }
        queryRequest.setOrderBy(sortField);
        queryRequest.setOrderDirection(sortOrder);
        
        return flowExecutionService.getFlowExecutionPage(page, queryRequest);
    }

    /**
     * 同步执行流程
     */
    @PostMapping("/execute/sync")
    @Operation(summary = "同步执行流程", description = "同步执行指定的流程定义")
    public Result<Object> executeFlowSync(@Valid @RequestBody FlowExecutionRequest request) {
        return flowExecutionService.executeFlowSync(
            request.getFlowCode(),
            request.getInputData(),
            request.getExecutorId(),
            request.getApplicationName()
        );
    }

    /**
     * 异步执行流程
     */
    @PostMapping("/execute/async")
    @Operation(summary = "异步执行流程", description = "异步执行指定的流程定义")
    public Result<String> executeFlowAsync(@Valid @RequestBody FlowExecutionRequest request) {
        return flowExecutionService.executeFlowAsync(
            request.getFlowCode(),
            request.getInputData(),
            request.getExecutorId(),
            request.getApplicationName()
        );
    }

    /**
     * 停止流程执行
     */
    @PostMapping("/{id}/stop")
    @Operation(summary = "停止流程执行", description = "停止正在执行的流程")
    public Result<Object> stopFlowExecution(
            @Parameter(description = "流程执行ID", required = true) @PathVariable Long id) {
        return flowExecutionService.stopFlowExecution(id);
    }

    /**
     * 重新执行流程
     */
    @PostMapping("/{id}/retry")
    @Operation(summary = "重新执行流程", description = "重新执行失败的流程")
    public Result<String> retryFlowExecution(
            @Parameter(description = "流程执行ID", required = true) @PathVariable Long id) {
        return flowExecutionService.retryFlowExecution(id);
    }

    /**
     * 根据ID获取流程执行记录
     */
    @GetMapping("/{id}")
    @Operation(summary = "获取流程执行记录", description = "根据ID获取流程执行记录详情")
    public Result<FlowExecutionDTO> getFlowExecutionById(
            @Parameter(description = "流程执行ID", required = true) @PathVariable Long id) {
        return flowExecutionService.getFlowExecutionById(id);
    }

    /**
     * 根据链路追踪ID获取流程执行记录
     */
    @GetMapping("/trace/{traceId}")
    @Operation(summary = "根据链路追踪ID获取执行记录", description = "根据链路追踪ID获取流程执行记录")
    public Result<FlowExecutionDTO> getFlowExecutionByTraceId(
            @Parameter(description = "链路追踪ID", required = true) @PathVariable String traceId) {
        return flowExecutionService.getFlowExecutionByTraceId(traceId);
    }

    /**
     * 根据流程编码获取执行记录列表
     */
    @GetMapping("/flow/{flowCode}")
    @Operation(summary = "根据流程编码获取执行记录", description = "根据流程编码获取执行记录列表")
    public Result<List<FlowExecutionDTO>> getFlowExecutionsByFlowCode(
            @Parameter(description = "流程编码", required = true) @PathVariable String flowCode,
            @Parameter(description = "记录数限制") @RequestParam(defaultValue = "100") Integer limit) {
        return flowExecutionService.getFlowExecutionsByFlowCode(flowCode, limit);
    }

    /**
     * 获取运行中的流程执行记录
     */
    @GetMapping("/running")
    @Operation(summary = "获取运行中的流程", description = "获取当前正在运行的流程执行记录")
    public Result<List<FlowExecutionDTO>> getRunningFlowExecutions() {
        return flowExecutionService.getRunningFlowExecutions();
    }

    /**
     * 获取失败的流程执行记录
     */
    @GetMapping("/failed")
    @Operation(summary = "获取失败的流程", description = "获取执行失败的流程记录")
    public Result<List<FlowExecutionDTO>> getFailedFlowExecutions(
            @Parameter(description = "记录数限制") @RequestParam(defaultValue = "100") Integer limit) {
        return flowExecutionService.getFailedFlowExecutions(limit);
    }

    /**
     * 获取流程执行统计信息
     */
    @GetMapping("/statistics")
    @Operation(summary = "获取流程执行统计", description = "获取流程执行的统计信息")
    public Result<Object> getFlowExecutionStatistics(
            @Parameter(description = "统计时间范围(天)") @RequestParam(defaultValue = "7") Integer days) {
        return flowExecutionService.getFlowExecutionStatistics(days);
    }

    /**
     * 获取流程执行趋势
     */
    @GetMapping("/trends")
    @Operation(summary = "获取流程执行趋势", description = "获取流程执行的趋势分析")
    public Result<Object> getFlowExecutionTrends(
            @Parameter(description = "趋势时间范围(天)") @RequestParam(defaultValue = "30") Integer days,
            @Parameter(description = "时间粒度") @RequestParam(defaultValue = "day") String granularity) {
        return flowExecutionService.getFlowExecutionTrends(days, granularity);
    }

    /**
     * 获取流程性能分析
     */
    @GetMapping("/performance")
    @Operation(summary = "获取流程性能分析", description = "获取流程执行的性能分析数据")
    public Result<Object> getFlowPerformanceAnalysis(
            @Parameter(description = "流程编码") @RequestParam(required = false) String flowCode,
            @Parameter(description = "分析时间范围(天)") @RequestParam(defaultValue = "7") Integer days) {
        return flowExecutionService.getFlowPerformanceAnalysis(flowCode, days);
    }

    /**
     * 清理过期的执行记录
     */
    @DeleteMapping("/cleanup")
    @Operation(summary = "清理过期执行记录", description = "清理指定天数之前的执行记录")
    public Result<Object> cleanupExpiredRecords(
            @Parameter(description = "保留天数", required = true) @RequestParam Integer retentionDays) {
        return flowExecutionService.cleanupExpiredRecords(retentionDays);
    }

    /**
     * 导出流程执行记录
     */
    @GetMapping("/export")
    @Operation(summary = "导出流程执行记录", description = "导出流程执行记录数据")
    public Result<Object> exportFlowExecutions(
            @Parameter(description = "流程编码") @RequestParam(required = false) String flowCode,
            @Parameter(description = "开始时间") @RequestParam(required = false) String startTime,
            @Parameter(description = "结束时间") @RequestParam(required = false) String endTime,
            @Parameter(description = "导出格式") @RequestParam(defaultValue = "excel") String format) {
        return flowExecutionService.exportFlowExecutions(flowCode, startTime, endTime, format);
    }

    /**
     * 获取流程执行日志
     */
    @GetMapping("/{id}/logs")
    @Operation(summary = "获取流程执行日志", description = "获取指定流程执行的日志信息")
    public Result<List<Object>> getFlowExecutionLogs(
            @Parameter(description = "流程执行ID", required = true) @PathVariable Long id) {
        return flowExecutionService.getFlowExecutionLogs(id);
    }

    /**
     * 获取节点执行详情
     */
    @GetMapping("/{id}/nodes")
    @Operation(summary = "获取节点执行详情", description = "获取流程执行中各节点的执行详情")
    public Result<List<Object>> getNodeExecutionDetails(
            @Parameter(description = "流程执行ID", required = true) @PathVariable Long id) {
        return flowExecutionService.getNodeExecutionDetails(id);
    }

    /**
     * 暂停流程执行
     */
    @PostMapping("/{id}/pause")
    @Operation(summary = "暂停流程执行", description = "暂停正在执行的流程")
    public Result<Object> pauseFlowExecution(
            @Parameter(description = "流程执行ID", required = true) @PathVariable Long id) {
        return flowExecutionService.pauseFlowExecution(id);
    }

    /**
     * 恢复流程执行
     */
    @PostMapping("/{id}/resume")
    @Operation(summary = "恢复流程执行", description = "恢复已暂停的流程执行")
    public Result<Object> resumeFlowExecution(
            @Parameter(description = "流程执行ID", required = true) @PathVariable Long id) {
        return flowExecutionService.resumeFlowExecution(id);
    }

    /**
     * 获取流程执行状态
     */
    @GetMapping("/{id}/status")
    @Operation(summary = "获取流程执行状态", description = "获取流程的当前执行状态")
    public Result<Object> getFlowExecutionStatus(
            @Parameter(description = "流程执行ID", required = true) @PathVariable Long id) {
        return flowExecutionService.getFlowExecutionStatus(id);
    }

    /**
     * 批量停止流程执行
     */
    @PostMapping("/batch-stop")
    @Operation(summary = "批量停止流程执行", description = "批量停止多个流程的执行")
    public Result<Object> batchStopFlowExecutions(@Valid @RequestBody BatchStopRequest request) {
        return flowExecutionService.batchStopFlowExecutions(request.getExecutionIds());
    }

    /**
     * 获取流程输入数据
     */
    @GetMapping("/{id}/input")
    @Operation(summary = "获取流程输入数据", description = "获取流程执行的输入数据")
    public Result<Object> getFlowInputData(
            @Parameter(description = "流程执行ID", required = true) @PathVariable Long id) {
        return flowExecutionService.getFlowInputData(id);
    }

    /**
     * 获取流程输出数据
     */
    @GetMapping("/{id}/output")
    @Operation(summary = "获取流程输出数据", description = "获取流程执行的输出数据")
    public Result<Object> getFlowOutputData(
            @Parameter(description = "流程执行ID", required = true) @PathVariable Long id) {
        return flowExecutionService.getFlowOutputData(id);
    }

    /**
     * 流程执行请求DTO
     */
    public static class FlowExecutionRequest {
        
        @NotBlank(message = "流程编码不能为空")
        @Parameter(description = "流程编码", required = true)
        private String flowCode;

        @Parameter(description = "输入数据")
        private Object inputData;

        @Parameter(description = "执行者ID")
        private Long executorId;

        @Parameter(description = "应用名称")
        private String applicationName;

        // Getter and Setter methods
        public String getFlowCode() {
            return flowCode;
        }

        public void setFlowCode(String flowCode) {
            this.flowCode = flowCode;
        }

        public Object getInputData() {
            return inputData;
        }

        public void setInputData(Object inputData) {
            this.inputData = inputData;
        }

        public Long getExecutorId() {
            return executorId;
        }

        public void setExecutorId(Long executorId) {
            this.executorId = executorId;
        }

        public String getApplicationName() {
            return applicationName;
        }

        public void setApplicationName(String applicationName) {
            this.applicationName = applicationName;
        }
    }

    /**
     * 批量停止请求DTO
     */
    public static class BatchStopRequest {
        
        @NotNull(message = "执行ID列表不能为空")
        @Parameter(description = "流程执行ID列表", required = true)
        private List<Long> executionIds;

        // Getter and Setter methods
        public List<Long> getExecutionIds() {
            return executionIds;
        }

        public void setExecutionIds(List<Long> executionIds) {
            this.executionIds = executionIds;
        }
    }
}